package com.liuqianfei.markme.rules.inline;

import com.liuqianfei.markme.core.Token;
import com.liuqianfei.markme.rules.AbstractState;
import com.liuqianfei.markme.rules.IAction;
import com.liuqianfei.util.RegExpUtil;
import com.liuqianfei.util.StringUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * @author liuqianfei
 */
public class AutolinkAction implements IAction
{
    /*eslint max-len:0*/
    String EMAIL_RE    = "^<([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>";
    String AUTOLINK_RE = "^<([a-zA-Z][a-zA-Z0-9+.\\-]{1,31}):([^<>\\x00-\\x20]*)>";

    @Override
    public boolean parse(AbstractState state, boolean silent, int startLine, int endLine)
    {
        String linkMatch, emailMatch, url, fullUrl, tail;
        int pos = state.getPos();
        Token token;

        if (state.getSrc().charAt(pos) != 0x3C/* < */)
            return false;

        tail = StringUtil.slice(state.getSrc(), pos);

        if (tail.indexOf('>') < 0)
            return false;

        if (RegExpUtil.match(AUTOLINK_RE, tail, false))
        {
            linkMatch = RegExpUtil.group(AUTOLINK_RE, tail, false, 0);
            if (null == linkMatch || linkMatch.length() < 2)
                return false;

            url = StringUtil.slice(linkMatch, 1, -1);

            fullUrl = state.getMd().normalizeLink(url);
            if (!state.getMd().validateLink(fullUrl))
                return false;

            if (!silent)
            {
                Map<String, String> attrs = new HashMap<>();
                attrs.put("href", fullUrl);

                token         = state.push("link_open", "a", 1);
                token.attrs   = attrs;
                token.markup  = "autolink";
                token.info    = "auto";

                token         = state.push("text", "", 0);
                token.content = state.getMd().normalizeLinkText(url);

                token         = state.push("link_close", "a", -1);
                token.markup  = "autolink";
                token.info    = "auto";
            }

            state.setPos(state.getPos() + linkMatch.length());
            return true;
        }

        if (RegExpUtil.match(EMAIL_RE, tail, false))
        {
            emailMatch = RegExpUtil.group(EMAIL_RE, tail, false, 0);
            if (null == emailMatch || emailMatch.length() < 2)
                return false;

            url = StringUtil.slice(emailMatch, 1, -1);

            fullUrl = state.getMd().normalizeLink("mailto:" + url);
            if (!state.getMd().validateLink(fullUrl))
                return false;

            if (!silent)
            {
                Map<String, String> attrs = new HashMap<>();
                attrs.put("href", fullUrl);

                token         = state.push("link_open", "a", 1);
                token.attrs   = attrs;
                token.markup  = "autolink";
                token.info    = "auto";

                token         = state.push("text", "", 0);
                token.content = state.getMd().normalizeLinkText(url);

                token         = state.push("link_close", "a", -1);
                token.markup  = "autolink";
                token.info    = "auto";
            }

            state.setPos(state.getPos() + emailMatch.length());
            return true;
        }

        return false;
    }
}
